/**************************************************************************
 *                              cEdit_methods.c
 *                            arranged by Scott J. Pearson
 * These are methods included in the original cloneedit.c that are necessary
 * for the execution of FPC. With only a couple exceptions, I have not
 * modified these.
*/

#include <stdio.h>
#include <gtk/gtk.h>
#include <strings.h>
#include <stdlib.h>
#include "fpp.h"
#include "float.h"
#include "cEdit.h"

/*** IMPORTED FROM ORIGINAL cloneedit.c ***/

BOOL bury(int c1,int c2);
BOOL unbury(int c1);
void deleteclone();
void initeditclone(int cloneindex);
void none();
void removeCloneFromMarkersList(int clonedisplayed,int markerindex);
void sortoutmarkerindex(void);
void deletemarker(int markerindex);
void freerootmarkerptr();
void freeedited();
extern void   markersinctgcount();

void settime(struct mytime *mytime);
BOOL checkctgwithmarker(int index);
void removeMarkerFromClonesList(int markerindex, int clonedisplayed);
void renameclone(int index);
void updateproj(void);
void initremarklist();
void initmarkerlist();
void initfpdatalist();
BOOL checkokaytobury(int c1, int c2);
int Zbury_type(int child, int parent);
void Zupdate_cin(int from, int to);
void renamemarker(int markerindex);
void move_selected(int from, int result, int distance);   /* not placed */
void markersetzero(void);    /* not placed */
void recalccontigs(void);   /* not placed */
void markercorrect(void);   /* not placed */
void contigindexfix(int from, int to);
void savectgchanges(void);
void resetctgforparentandburied(int parentindex);
void resetMarkersForCloneChangingCtg(int cloneindex);
void addCloneToMarkerList(int cloneindex, int markerindex);
void freetempmemory();
void recalcindexes();

static BOOL clone_exists(char *temp);


extern void refreshlist();
extern int PRTMESS;
extern GtkWidget *ctg_window;   /*fred 4/25/03*/
extern void gelquit();
extern int calcmarkerctgpos(struct markerctgpos *pos, int markerindex);
extern void recalccontigx(int ctg);
extern void sortmarkers();
extern int findBuriedClones(int parentindex, struct CharList** CL);
extern void create_mainWindow(CLONE *currclone, int cloneindex);

extern GtkWidget* markerEditWindow;



struct editfpdata{
  int number;
  char fpchar[CLONE_SZ+1];
  char gelname[GEL_SZ+1];
  int b1,b2,box;
  struct editfpdata *next;
};

static struct editfpdata *editfpdataroot=NULL;


/***************** IMPORTED FROM CLONEEDIT.C *******************/
BOOL unbury(int c1)
{
  CLONE *clone1,*clone2;
  int i;
  BOOL parent,psparent,found;
  char str1[180];
  struct contig *p;

  clone1 = arrp(acedata,c1,CLONE);
  if(clone1->parent == -1){
    sprintf(str1,"Clone %s is not buried",clone1->clone);
    if (PRTMESS) displaymess(str1);
    return FALSE;
  }
  else{
    clone2 = arrp(acedata,clone1->parent,CLONE);
    /* Is it the last one, if so set clone2 to no longer be a parent */
    if(root!= NULL){
      if(arrp(acedata,root->next,CLONE)->ctg == clone1->ctg){
        psparent = parent = FALSE;
        p = root;
        while(!parent && p != NULL){
          if ((arrp(acedata,p->next,CLONE)->parent == clone1->parent)
              && (p->next != c1)){
            if(arrp(acedata,p->next,CLONE)->mattype & PSEUDO)
              psparent = TRUE;
            else
              parent = TRUE;
          }
          p = p->new;
        }
        if(!parent){
          if(psparent)
            clone2->mattype = PSPARENT;
          else
            clone2->mattype = 0;
        }
        clone1->mattype = 0;
        clone1->parent = -1;
        strcpy(clone1->match,"      ");
        if(clone1->highcol == FRIEND)
          clone1->highcol = 0;
        if(clone2->highcol == FRIEND)
          clone2->highcol = 0;
        sprintf(str1,"Clone %s unburied from parent %s", clone1->clone,
                clone2->clone);
        if (PRTMESS) displaymess(str1);
        settime(&clone2->modified_date);
        settime(&clone1->modified_date);
        return TRUE;
      }
    }
  }
  found = FALSE;
  for(i=0;i<arrayMax(acedata);i++){
    if(!found){
      if(arrp(acedata,i,CLONE)->parent == clone1->parent && i != c1)
        found = TRUE;
    }
  }
  if(!found)
    clone2->mattype = 0;
  clone1->mattype = 0;
  clone1->parent = -1;
  strcpy(clone1->match,"      ");
  if(clone1->highcol == FRIEND)
    clone1->highcol = 0;
  if(clone2->highcol == FRIEND)
    clone2->highcol = 0;
  sprintf(str1,"Clone %s unburied from parent %s",clone1->clone,clone2->clone);
  if (PRTMESS) displaymess(str1);
  settime(&clone2->modified_date);
  settime(&clone1->modified_date);
  return TRUE;
}

/****************************************************************
                DEF: deleteclone
Cancels the clone and removes the edit window
modified by SJP
*****************************************************************/
void deleteclone()
{
  BOOL carryon = TRUE,first = FALSE,remove = FALSE;
  CLONE *clone;
  struct markertop *ptr;
  struct CharList* BC;
  struct CharList* currCL;
  int cloneindex;
  int currindex;
  int numClones;
  int i;

  clone = arrp(acedata,clonedisplayed,CLONE);
  if((clone->mattype & PARENT || clone->mattype & PSPARENT) && carryon){
    /* unbury children */
    if (!fppFind(acedata, clone->clone, &cloneindex, cloneOrder))
    {
       printf("ERROR: Cannot find cloneindex for clone %s\n", clone->clone);
    }
    numClones = findBuriedClones(cloneindex, &BC);
    currCL = BC;
    for (i = 0; i < numClones; i++)
    {
      if (fppFind(acedata, currCL->name, &currindex, cloneOrder))
      {
         unbury(currindex);
         currCL = currCL->next;
      }
    }
  }
  if(clone->match[0] != ' '){
    if (fppFind(acedata, clone->clone, &cloneindex, cloneOrder))
    {
       unbury(cloneindex);
    }
  }
  if(clone->seqstat!=0 && clone->seqstat!=CANCELLED){
    displaymess("Delete clone ERROR message:");
    displaymess("  Clone has a sequence state. Therefore cannot be cancelled.");
    return;
  }
   
  if(clone->marker != NULL && carryon){
    ptr= clone->marker;
    first = TRUE;
    while(ptr!=NULL && first){
      if (arrp(markerdata,ptr->markerindex,MARKER)->nextclone ==NULL) {
         if (!messQuery("Some marker(s) will be deleted with the clone deletion. Is this okay?"))
            carryon = FALSE;
        first = FALSE;
        remove = TRUE;
      }
      ptr = ptr->nextmarker;
    }
  }
  if(carryon){
    if(clone->marker != NULL){
      remove = checkctgwithmarker(clonedisplayed);
      ptr= clone->marker;
      while(ptr!=NULL){
        removeMarkerFromClonesList(ptr->markerindex,clonedisplayed);
        if(arrp(markerdata,ptr->markerindex,MARKER)->nextclone ==NULL)
          sprintf(ptr->marker,"!%s",ptr->marker);
        removeCloneFromMarkersList(clonedisplayed,ptr->markerindex);
        ptr = ptr->nextmarker;
      }
      if(remove){
        sortoutmarkerindex();
      }
    }
    renameclone(clonedisplayed);
    clhigh = NULL;
    newctg = TRUE;
    if(ctg_window!=NULL){
      if(contigs[currentctg].count == 0){
        if(ctg_window!=NULL) gtk_widget_destroy(ctg_window);
      }
      else
        ctgdisplay(currentctg);
    }
    refreshlist();
    updateproj();
    if (graphActivate(gcloneedit)) graphDestroy();
  }
}

void initeditclone(int cloneindex)
{
  CLONE* clone;
  if (active==EDITNOTHING) {
    clonedisplayed = cloneindex;
    clone = arrp(acedata,clonedisplayed,CLONE);
    lasteditbox = 1;
    graphDestroy();
    active += EDITCLONE;
    initremarklist();
    initmarkerlist();
    initfpdatalist();
    create_mainWindow(clone, cloneindex);
  }
  else {
    printf("%d %d Edit session\n", active, EDITNOTHING);
    displaymess("Only one edit session allowed at a time");
    if(graphActivate(gcloneedit)) graphPop();
    if(graphActivate(gmarkeredit2)) graphPop();
    return;
  }
}


BOOL bury(int c1,int c2)
/* need to bury c1 in c2. i.e c1 become child c2 become parent */
{
  CLONE *clone1,*clone2;
  char str1[60];

  if (c1 < 0 || c2 < 0) { /* cari 29 june 04 */
     printf("Warning: Bad clone indices, cannot bury\n");
     return FALSE;
  }
  clone1 = arrp(acedata,c1,CLONE);
  clone2 = arrp(acedata,c2,CLONE);

  if(checkokaytobury(c1,c2)){
    settime(&clone1->modified_date);
    settime(&clone2->modified_date);
    clone1->parent= c2;
    clone1->mattype = Zbury_type(c1,c2);
    strcpy(clone1->match,clone2->clone);
    if(clone1->mattype & PSEUDO){
      if(!(clone2->mattype & PARENT))
        clone2->mattype = PSPARENT;
    }
    else
      clone2->mattype = PARENT;
    sprintf(str1,"Clone %s buried in clone %s",clone1->clone,clone2->clone);
    if (PRTMESS) displaymess(str1);
    if(clone2->highcol==HIGHLIGHT)
      clone1->highcol = FRIEND;
    if(clone1->highcol == HIGHLIGHT)
      clone1->highcol = FRIEND;
    return TRUE;
  }
  else
    return FALSE;
}

void none()
{
}

void removeCloneFromMarkersList(cloneindex,markerindex)
{
  struct marker *marker;
  struct markerclone *markerclone;

  marker = arrp(markerdata,markerindex,MARKER);

  if(marker->cloneindex == cloneindex){
    if(marker->nextclone == NULL)  /* i.e we are about to remove the only clone for this marker */
      renamemarker(markerindex);
    else{
      markerclone = marker->nextclone;
      marker->cloneindex = markerclone->cloneindex;
      marker->nextclone = markerclone->nextclone;
    }
  }
  else{
    markerclone = marker->nextclone;
    if(markerclone->cloneindex == cloneindex){
      marker->nextclone = markerclone->nextclone;
    }
    else{
      while(markerclone->nextclone !=NULL){
        if(markerclone->nextclone->cloneindex == cloneindex){
          markerclone->nextclone =  markerclone->nextclone->nextclone;
          break;
        }
        /* WN 4/04 Adding this line for obvious reasons. Thought about rewriting
           this search but on closer inspection it might not be more complex
           than it needs to be. Anyway it works. */
        markerclone = markerclone->nextclone; 
      }
    }
  }
}


void sortoutmarkerindex()
{
  int i,index;
  struct markertop *top;
  MARKEREDITLIST *top2;
  Array temp_mark = 0;
  struct marker *marker;

  temp_mark = arrayReCreate(temp_mark,arrayMax(markerdata),MARKER);
  for(i=0;i<arrayMax(markerdata);i++){
    marker = arrp(markerdata,i,MARKER);
    if(marker->marker[0] != '!'){
      if(fppInsert(temp_mark,marker->marker,&index,markerOrder))
        array(temp_mark,index,MARKER) = *marker;
      else
        printf("ERROR delete marker error.");
    }
  }
  arrayDestroy(markerdata);
  markerdata = temp_mark;



  for(i=0;i<arrayMax(acedata);i++){
    top = arr(acedata,i,CLONE).marker;
    while(top !=NULL){
      /* top may never go NULL */
      if(fppFind(markerdata,top->marker,&index, markerOrder))
        top->markerindex = index;
      top = top->nextmarker;
    }
  }

  top2 = rootmarkerptr;
  while(top2 !=NULL){
    if(fppFind(markerdata,top2->marker,&index, markerOrder))
      top2->markerindex = index;
    top2 = top2->nextmarker;
  }

}

/* modified by SJP */
void deletemarker(int markerindex)
{
  int i,index3;
  struct marker *marker;
  Array markerdatatemp = 0;
  struct markertop *clonemkr;
  struct markerclone *mkrclone;
  
  marker = arrp(markerdata, markerindex, MARKER);
  clonemkr = arrp(acedata, marker->cloneindex, CLONE)->marker;
  if (clonemkr->markerindex == markerindex)
  {
    arrp(acedata, marker->cloneindex, CLONE)->marker = clonemkr->nextmarker;
  }
  else
  {
    while (clonemkr->nextmarker != NULL)
    {
      if (clonemkr->nextmarker->markerindex == markerindex)
      {
        clonemkr->nextmarker = clonemkr->nextmarker->nextmarker;
        break;
      }
      clonemkr = clonemkr->nextmarker;
     }
   }

   mkrclone = marker->nextclone;
   if (mkrclone != NULL)
   {
      clonemkr = arrp(acedata, mkrclone->cloneindex, CLONE)->marker;
      if (clonemkr->markerindex == markerindex)
      {
        arrp(acedata, mkrclone->cloneindex, CLONE)->marker = clonemkr->nextmarker;
      }
      else
      {
        while (clonemkr->nextmarker != NULL)
        {
          if (clonemkr->nextmarker->markerindex == markerindex)
          {
            clonemkr->nextmarker = clonemkr->nextmarker->nextmarker;
            break;
          }
          clonemkr = clonemkr->nextmarker;
        }
      }
   }

  markerdatatemp = arrayReCreate (markerdatatemp, arrayMax(markerdata) , MARKER);
  for(i=0;i<arrayMax(markerdata);i++){
    if(i!=markerindex){
      marker = arrp(markerdata,i,MARKER);
      marker->box = 0;
      marker->colour = 0;
      if(fppInsert(markerdatatemp,marker->marker,&index3, markerOrder)){
        array(markerdatatemp,index3,MARKER) = *marker;
      }
      else
        printf("ERROR delete marker bit\n");
    }
  }
  arrayDestroy(markerdata);
  markerdata = markerdatatemp;

}


BOOL checkctgwithmarker(int index)
{
  BOOL found = FALSE,remove = FALSE;
  CLONE *clone;
  struct marker *marker;
  struct markertop *ptr;
  struct markerctgpos *pos,*last;
  struct markerclone *nextclone;

  clone = arrp(acedata,index,CLONE);
  ptr = clone->marker;
  while(ptr!= NULL){ /* for each maker */
    found = FALSE;
    marker = arrp(markerdata,ptr->markerindex,MARKER);
    if(marker->cloneindex != index){
      if(arrp(acedata,marker->cloneindex,CLONE)->ctg == clone->ctg)
        found = TRUE;
    }
    if(!found){
      nextclone = marker->nextclone;
      while(nextclone != NULL){
        if(nextclone->cloneindex != index){
          if(arrp(acedata,nextclone->cloneindex,CLONE)->ctg == clone->ctg)
            found = TRUE;
        }
        nextclone=nextclone->nextclone;
      }
    }

    if(!found){ /* markerctg no longer should exist */
      remove = TRUE;
      if(marker->pos != NULL){
        pos = marker->pos;
        if(pos->ctg == clone->ctg){
          marker->pos = marker->pos->next;
        }
        else{
          while(pos!=NULL && !found){
            last = pos;
            pos=pos->next;
            if(pos!= NULL){
              if(pos->ctg == clone->ctg){
                last->next = pos->next;
                found = TRUE;
              }
            }
          }
        }
      }
    }
    ptr= ptr->nextmarker;
  }
  return remove;
}

void removeMarkerFromClonesList(markerindex,cloneindex)
{
  BOOL deleted = FALSE;
  CLONE *clone;
  struct markertop *ptr;

  clone = arrp(acedata,cloneindex,CLONE);
  if(clone->marker != NULL){
    if(clone->marker->markerindex == markerindex){
      clone->marker = clone->marker->nextmarker;
    }
    else{
      ptr = clone->marker;
      while(ptr->nextmarker != NULL && !deleted ){
        if(ptr->nextmarker->markerindex == markerindex){
          deleted = TRUE;
          ptr->nextmarker = ptr->nextmarker->nextmarker;
        }
        if(!deleted)
          ptr = ptr->nextmarker;
      }
    }
  }
}

void renameclone(int cloneindex)
{
  Array acedata2=0;
  int i;
  CLONE *clone;
  int index,newindex;
  char temp[12],str1[40];

   
  clone= arrp(acedata,cloneindex,CLONE);

  sprintf(str1,"Clone %s cancelled",clone->clone);
  displaymess(str1);
  sprintf(temp,"!%s",clone->clone);
  strcpy(clone->clone,temp);
  clone->ctg = 0;
  settime(&clone->modified_date);
  strcpy(clone->chctg,"ctg0");
  acedata2 = arrayReCreate(acedata2, arrayMax(acedata), CLONE);
  for(i=0;i<arrayMax(acedata);i++){
    clone = arrp(acedata,i,CLONE);
    if(clone->parent < clonedisplayed && clone->parent != -1)
      clone->parent++;
  here:
    if(fppInsert(acedata2,clone->clone,&index,cloneOrder)){
      array(acedata2,index,CLONE) = *clone;
    }
    else{
      sprintf(temp,"!%s",clone->clone);
      strcpy(clone->clone,temp);
      goto here;
    }
  }
  arrayDestroy(acedata);
  acedata = acedata2;

  recalccontigs();
  gelquit();
  if(graphActivate(g3))
    fpquit();

  markersetzero();
  markercorrect();
  if(fppFind(acedata,temp,&newindex,cloneOrder))
    contigindexfix(clonedisplayed,newindex);
}

void initremarklist()
{
  struct remark *remark, *ptr;

/* first make copy of remarks */

  remark = arrp(acedata,clonedisplayed,CLONE)->remark;
  if(remark == NULL){
    tempremark = (struct remark *)messalloc((sizeof(struct remark)));
    strcpy(tempremark->message,"");
    tempremark->next = NULL;
    editremarkptr = tempremark;
  }
  else{
    tempremark = (struct remark *)messalloc((sizeof(struct remark)));
    ptr = tempremark;
    strcpy(ptr->message,remark->message);
    ptr->next = NULL;
    editremarkptr = tempremark;
    while(remark->next!=NULL){
      remark=remark->next;
      ptr->next =  (struct remark *)messalloc((sizeof(struct remark)));
      ptr=ptr->next;
      ptr->next = NULL;
      strcpy(ptr->message,remark->message);
      editremarkptr = remark;
    }
  }

/* make copy of fp remarks */

  remark = arrp(acedata,clonedisplayed,CLONE)->fp_remark;
  if(remark == NULL){
    tempremarkfp = (struct remark *)messalloc((sizeof(struct remark)));
    strcpy(tempremarkfp->message,"");
    tempremarkfp->next = NULL;
    editremarkptr = tempremarkfp;
  }
  else{
    tempremarkfp = (struct remark *)messalloc((sizeof(struct remark)));
    ptr = tempremarkfp;
    strcpy(ptr->message,remark->message);
    ptr->next = NULL;
    editremarkptr = tempremarkfp;
    while(remark->next!=NULL){
      remark=remark->next;
      ptr->next =  (struct remark *)messalloc((sizeof(struct remark)));
      ptr=ptr->next;
      ptr->next = NULL;
      strcpy(ptr->message,remark->message);
      editremarkptr = remark;
    }
  }
}

void initmarkerlist()
{
  struct markertop *ptr;
  MARKEREDITLIST *tempptr=NULL;
  BOOL first = TRUE;

  ptr = arrp(acedata,clonedisplayed,CLONE)->marker;

  rootmarkerptr = NULL;
  while(ptr != NULL){
    if(first){
      rootmarkerptr =
            (struct markereditlist *)messalloc((sizeof(struct markereditlist)));
      first = FALSE;
      tempptr = rootmarkerptr;
    }
    else{
      tempptr->nextmarker =
            (struct markereditlist *)messalloc((sizeof(struct markereditlist)));
      tempptr = tempptr->nextmarker;
    }
    tempptr->markerindex = ptr->markerindex;
    tempptr->nextmarker = NULL;
    strcpy(tempptr->marker,ptr->marker);
    tempptr->status = 0;
    ptr = ptr->nextmarker;
  }
}


void initfpdatalist()
{
  BOOL first = TRUE;
  struct editfpdata *editfpdataptr=NULL;
  struct fpdata *temp1;

  temp1 = clone2.fp;
  while(temp1 != NULL){
    if(first){
      editfpdataroot =
                    (struct editfpdata *)messalloc((sizeof(struct editfpdata)));
      editfpdataptr = editfpdataroot;
      first = FALSE;
    }
    else{
      editfpdataptr->next =
                    (struct editfpdata *)messalloc((sizeof(struct editfpdata)));
      editfpdataptr = editfpdataptr->next;
    }
    strcpy(editfpdataptr->gelname, temp1->gelname);
    editfpdataptr->b1 = temp1->b1;
    editfpdataptr->b2 = temp1->b2;
    editfpdataptr->box = -1;
    strcpy(editfpdataptr->fpchar,temp1->fpchar);
    editfpdataptr->next = NULL;
    temp1 = temp1->next;
  }
  if(first)
    editfpdataroot = NULL;
}


BOOL checkokaytobury(int c1, int c2)
{
  CLONE *clone1,*clone2;
  char str1[180];

  clone1 = arrp(acedata,c1,CLONE);
  clone2 = arrp(acedata,c2,CLONE);

  if(clone1->ctg != clone2->ctg){
    sprintf(str1,"Clone %s is in %s, clone %s is in %s. Therefore cannot be buried.",clone1->clone,clone1->chctg,clone2->clone,clone2->chctg);
    displaymess(str1);
    return FALSE;
  }
  if(clone1->parent != -1){
    sprintf(str1,"Clone %s has a parent, therefore cannot be buried in %s.",clone1->clone, clone2->clone);
    displaymess(str1);
    return FALSE;
  }
  if(clone2->mattype != 0 && clone2->mattype != PARENT && clone2->mattype != PSPARENT){
    sprintf(str1,"Clone %s is buried, therefore cannot have buried clone %s.",
                           clone2->clone, clone1->clone);
    displaymess(str1);
    return FALSE;
  }
  return TRUE;
}


void renamemarker(int markerindex)
{
  struct marker *marker;
  char str1[20];

  marker = arrp(markerdata,markerindex,MARKER);
  printf("Removing marker %s\n",marker->marker);  
  sprintf(str1,"!%s",marker->marker);
  strcpy(marker->marker,str1);
  marker->status = DELETED;
  sortoutmarkerindex();
  if(graphActivate(g2)) 
  {
     graphDestroy();
  }
  if (markerEditWindow)
  {
     gtk_widget_destroy(markerEditWindow);
  }
  if (graphActivate(gmarker))
  {
     graphDestroy();
  }
}


void contigindexfix(int from,int to)
{
  struct contig *p;

  Zupdate_cin(from , to);

  p = root;

  while(p!=NULL){
    if(from > to){
      if(p->next >= to && p->next < from)
        p->next++;
      else if(p->next == from)
        p->next = to;
    }
    else if(to > from){
      if(p->next == from)
        p->next = to;
      else if(p->next > from && p->next <= to)
        p->next--;
    }
    p = p->new;
  }
}

void savectgchanges()
{
  CLONE *clone;

  int oldctg;
  BOOL clonechanged = FALSE;
  BOOL markerorder,found;
  struct markerlist *p2;
  struct markertop *markerptr;
  struct markerctgpos *pos;
  struct marker *marker;

  clone = arrp(acedata,clonedisplayed,CLONE);

  oldctg = clone->ctg;
  if (clone->x != clone2.x || clone->y != clone2.y)
     clonechanged = TRUE;
  clone->y = clone2.y;
  clone->x = clone2.x;

  if ((clone->class != clone2.class) || (clone->seqstat != clone2.seqstat)
     || (clone->seqtype != clone2.seqtype)  /* ADD 19mar99 */
     || (strcmp(clone->match,clone2.match) != 0)
     || (clone2.parent != clone->parent))
     clonechanged = TRUE;
                           /* FIX 17june99 changed from avoid to cancelled */
  if ((clone->seqstat != clone2.seqstat) && (clone->seqstat == 0)
      && (clone2.seqstat != CANCELLED))
     contigs[clone->ctg].seq++;
  else if ((clone->seqstat != clone2.seqstat) && (clone2.seqstat == 0)
           && (clone->seqstat != CANCELLED))
    contigs[clone->ctg].seq--;

  clone->class = clone2.class;
  clone->seqstat = clone2.seqstat;
  clone->seqtype = clone2.seqtype; /* ADD 19mar99 */
  strcpy(clone->match, clone2.match);

  if (clonechanged) {
    settime(&clone->modified_date);
    recalccontigx(clone->ctg);
    if (oldctg == clone->ctg) {
      markerorder = FALSE;
      markerptr = clone->marker;
      while (markerptr != NULL) {
        marker = arrp(markerdata,markerptr->markerindex,MARKER);
        pos = marker->pos;
        while (pos != NULL) {
          if (pos->ctg == clone->ctg){
            markerorder = TRUE;
            pos->pos = calcmarkerctgpos(pos,markerptr->markerindex);
            p2 = markerlistroot;
            found = FALSE;
            while (p2 != NULL && !found) {
              if (p2->markerindex == markerptr->markerindex) {
                found = TRUE;
                p2->midpt = pos->pos;
              }
              p2 = p2->next;
            }
          }
          pos= pos->next;
        }
        markerptr = markerptr->nextmarker;
      }
      if (markerorder)
        sortmarkers();
    }
  }
  if (clone->x > clone->y) {
    clone->x = clone2.y;
    clone->y = clone2.x;
  }
}

void resetctgforparentandburied(int parentindex)
{
  CLONE *clone;
  int i;
  char str1[80];

  clone =arrp(acedata,parentindex,CLONE);
  resetMarkersForCloneChangingCtg(parentindex);
  sprintf(str1,"Clone %s moved from ctg%d to ctg%d",clone->clone,clone->ctg,clone2.ctg);
  if (PRTMESS) displaymess(str1);
  clone->ctg = clone2.ctg;
  settime(&clone->modified_date);
  clone->x = contigs[clone->ctg].left;
  if (clone->fp != NULL)
    clone->y = contigs[clone->ctg].left + clone->fp->b2;
  else
    clone->y = contigs[clone->ctg].left + 1;

  sprintf(clone->chctg,"ctg%d",clone->ctg);
  for (i=0;i<arrayMax(acedata);i++){
    clone = arrp(acedata,i,CLONE);
    if (clone->parent == parentindex){
      resetMarkersForCloneChangingCtg(i);
      sprintf(str1,"Clone %s moved from ctg%d to ctg%d",clone->clone,clone->ctg, clone2.ctg);
      if (PRTMESS) displaymess(str1);
      clone->ctg = clone2.ctg;
      settime(&clone->modified_date);
      sprintf(clone->chctg,"ctg%d",clone->ctg);
      clone->x = contigs[clone->ctg].left;
      if (clone->fp != NULL)
        clone->y = contigs[clone->ctg].left + clone->fp->b2;
      else
        clone->y = contigs[clone->ctg].left + 1;
    }
  }
}


void resetMarkersForCloneChangingCtg(int cloneindex)
{
  struct markertop *markertop;
  int oldctg,countold,countnew;
  BOOL found;
  struct markerclone *cloneptr;
  struct markerctgpos *pos;
  struct marker *marker;

  markertop = arrp(acedata,cloneindex,CLONE)->marker;
  oldctg = arrp(acedata,cloneindex,CLONE)->ctg;
  while (markertop!=NULL) { /* for each marker */
    marker = arrp(markerdata,markertop->markerindex,MARKER);
    countold = countnew = 0;
    if (arrp(acedata,marker->cloneindex,CLONE)->ctg == oldctg)
      countold = 1;
    if (arrp(acedata,marker->cloneindex,CLONE)->ctg == clone2.ctg)
      countnew = 1;
    cloneptr = marker->nextclone;
    while (cloneptr!=NULL){
      if (arrp(acedata,cloneptr->cloneindex,CLONE)->ctg == oldctg)
        countold++;
      if (arrp(acedata,cloneptr->cloneindex,CLONE)->ctg == clone2.ctg)
        countnew++;
      cloneptr = cloneptr->nextclone;
    }
    if (countold == 1 && countnew == 0) {
      /* i.e. the marker is only listed once */
      pos = marker->pos;
      found = FALSE;
      while(pos != NULL && !found){
        if(pos->ctg == oldctg){
          pos->ctg = clone2.ctg;
          contigs[oldctg].markers--;
          contigs[clone2.ctg].markers++;
          found = TRUE;
        }
        pos=pos->next;
      }
    }
    else if (countold == 1 && countnew != 0) {
      contigs[oldctg].markers--;
      pos = marker->pos;
      found = FALSE;
      if (marker->pos->ctg == oldctg)
        marker->pos = marker->pos->next;
      else{
        while (pos->next != NULL && !found) {
          if (pos->next->ctg == oldctg) {
            pos->next = pos->next->next;
            found = TRUE;
          }
          else
            pos=pos->next;
        }
      }
    }
    else if (countold >= 2) {/* i.e. it exists more than once*/
      if (countnew == 0) { /* new ctg pos does not exist */
        contigs[clone2.ctg].markers++;
        pos = marker->pos;
        found = FALSE;
        if (pos == NULL) {
          marker->pos =
               (struct markerctgpos *)messalloc((sizeof(struct markerctgpos)));
          pos = marker->pos;
        }
        else{
          while (pos->next != NULL) {
            pos= pos->next;
          }
          pos->next =
               (struct markerctgpos *) messalloc((sizeof(struct markerctgpos)));
          pos= pos->next; /* FIX 26mar99 */
        }
        pos->next = NULL;
        pos->ctg = clone2.ctg;
        pos->pos = (int)(clone2.x +clone2.y)/2;
      }
      else { /* ctgpos already exists MAY WANT TO UPDATE IT SOMETIME */
      }
    }
    else
      printf("WOOOOW ERROR marker not found for clone???\n");
    markertop = markertop->nextmarker;
  }
}

void addCloneToMarkerList(cloneindex,markerindex)
{       
  struct marker *marker;
  struct markerclone *markerclone;
  CLONE *clone; 
      
  marker = arrp(markerdata,markerindex,MARKER);
  if(marker->colour == HIGHLIGHT){
    clone = arrp(acedata,cloneindex,CLONE);
    clone->highcol = FRIEND;
  }
  markerclone =marker->nextclone;
  if(markerclone == NULL){
    marker->nextclone = (struct markerclone *)
                        messalloc((sizeof(struct markerclone)));  
    markerclone  = marker->nextclone;
  }       
  else{   
    while(markerclone->nextclone != NULL)
      markerclone = markerclone->nextclone;
    markerclone->nextclone = (struct markerclone *)
                             messalloc((sizeof(struct markerclone)));
    markerclone = markerclone->nextclone;
  } 
  markerclone->cloneindex = cloneindex;
  markerclone->nextclone = NULL;
}       
      
void change_clone_name(char* chaddname)
{
  BOOL carryon = TRUE,exists=FALSE;
  struct fpdata *start,*fp;
  int index;
  CLONE *clone,*clone2;
  int i;
  char str1[100];

  strcpy(chfpname,arrp(acedata,clonedisplayed,CLONE)->clone);
  if(strlen(chaddname)==0)
    return;
  if(clone_exists(chaddname)){
    exists = TRUE;
	/* sness */
	/*    if(!graphQuery("New name exists. Do you want me to still change.")) */
    if(!messQuery("New name exists. Do you want me to still change."))
      carryon = FALSE;
  }
  if(carryon){
    if(exists){
      /* fred 8/15/03 sprintf(str1, "Renaming %s to %s",clone->clone,chaddname);*/
      sprintf(str1, "Renaming %s to %s",chfpname,chaddname);
      displaymess(str1);
      fppFind(acedata,chaddname,&index,cloneOrder);
      if(clonedisplayed == index){
	clone = arrp(acedata,index,CLONE);
	strcpy(clone->clone,chaddname);
	freetempmemory();  
	editmenustatus = 0;
	active -= EDITCLONE;    
	initeditclone(clonedisplayed);
	
	update = TRUE;
	newctg = TRUE;
	if(graphActivate(g5))
	  graphDestroy();
	if(ctg_window!=NULL)
	  ctgdisplay(currentctg);
	if(graphActivate(g2) &&(classctg != MARKERCLASS))
	  graphDestroy();
	return;
      }
      clone = arrp(acedata,index,CLONE);
      fp =clone->fp;
      if(fp !=NULL){
	while(fp->next != NULL)
	  fp = fp->next;
	fppFind(acedata,chfpname,&index,cloneOrder);
	fp->next = arrp(acedata,index,CLONE)->fp;
	start = fp->next;
      }
      else{
	clone->fp  = arrp(acedata,index,CLONE)->fp;
	start = fp->next;
      }
      while(start!= NULL){
	if(start->fpchar[0] == ' ')
	  strcpy(start->fpchar,chfpname);
	start = start->next;
      }
      clone = arrp(acedata,index,CLONE);
      strcpy(clone->clone,"#");
    }
    else{
      clone = arrp(acedata,clonedisplayed,CLONE);
      fp =clone->fp;
      while(fp!= NULL){
	if(fp->fpchar[0] == ' ')
	  strcpy(fp->fpchar,clone->clone);
	fp = fp->next;
      }
      if(clone->mattype & PARENT || clone->mattype & PSPARENT){
	for(i=0;i<arrayMax(acedata);i++){
	  clone2 = arrp(acedata,i,CLONE);
	  if(clone2->parent == clonedisplayed)
	    strcpy(clone2->match,chaddname);
	}
      }
      strcpy(clone->clone,chaddname);
      settime(&clone->modified_date);
    }
    recalcindexes();
    freetempmemory();  
    editmenustatus = 0;
    fppFind(acedata,chaddname,&clonedisplayed,cloneOrder);
    
  }
}

void recalcindexes()
{
  Array acedata2=0;
  int i;
  CLONE *clone;
  int index;
  char str1[80];

  acedata2 = arrayReCreate(acedata2, arrayMax(acedata), CLONE);
  for(i=0;i<arrayMax(acedata);i++){
    clone = arrp(acedata,i,CLONE);
    if(clone->clone[0] != '#'){
      if(fppInsert(acedata2,clone->clone,&index,cloneOrder)){
	array(acedata2,index,CLONE) = *clone;
      }
      else
	printf("ERROR redo clone array. Please report this.");
    }
  }
  arrayDestroy(acedata);
  acedata = acedata2;

  recalccontigs();
  
  markersetzero();
  markercorrect();

/* reset children's parent pointer */
  for(i=0;i<arrayMax(acedata);i++){
    clone = arrp(acedata,i,CLONE);
    if(clone->parent != -1){
      if(fppFind(acedata,clone->match,&index,cloneOrder))
        clone->parent = index;
      else{
        sprintf(str1,"ERROR could not find parent %s for clone %s",clone->match,clone->clone);
        printf("%s\n",str1);
        displaymess(str1);
      }
    }
  }
  /* il 6/5/96 Kill fingerprint and gel maps */
  gelquit();
  if(graphActivate(g3))
    fpquit();
}


void freetempmemory()
{
  struct remark *ptr,*p2;

  ptr = tempremark; 
  if(ptr != NULL){
    while(ptr->next != NULL){
      p2 = ptr->next;
      messfree(ptr);
      ptr = p2;
    }
  }
  messfree(ptr);
  ptr = tempremarkfp;  
  if(ptr != NULL){
    while(ptr->next != NULL){
      p2 = ptr->next;
      messfree(ptr);
      ptr = p2;
    }
  }
  freerootmarkerptr();
  freeedited();
}
void freerootmarkerptr()
{
  MARKEREDITLIST *ptr1,*ptr2;

  ptr1 = rootmarkerptr;
  while(ptr1!=NULL){
    ptr2 = ptr1->nextmarker;
    messfree(ptr1);
    ptr1 = ptr2;
  }
  rootmarkerptr = NULL;
}

void freeedited()
{
  struct editfpdata *p,*p2;

  p = editfpdataroot;
  while(p!=NULL){
    p2= p->next;
    messfree (p);
    p = p2;
  }
}

static BOOL clone_exists(char *temp)
{
  int index;

  if(fppFind(acedata,temp,&index,cloneOrder))
    return TRUE;
  else
    return FALSE;
}
